/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.examples.modules.minicomposer; import java.io.*; import java.util.*; import javax.swing.SwingUtilities; import javax.swing.event.*; import javax.swing.text.*; import org.openide.cookies.EditorCookie; import org.openide.loaders.MultiDataObject; import org.openide.text.*; import org.openide.util.*; import org.openide.util.io.FoldingIOException; public class ScoreSupport implements ScoreCookie, Runnable, DocumentListener, ChangeListener { private MultiDataObject.Entry entry; private EditorCookie edit; private Task prepareTask; /** * @associates ChangeListener */ private Set listeners; private Score score; private IOException parseException; public ScoreSupport (MultiDataObject.Entry entry, EditorCookie edit) { this.entry = entry; this.edit = edit; prepareTask = null; listeners = new HashSet (); score = null; parseException = null; if (edit instanceof EditorSupport) { ((EditorSupport) edit).addChangeListener (WeakListener.change (this, edit)); } } public void stateChanged (ChangeEvent e) { invalidateLater (); } public synchronized void addChangeListener (ChangeListener l) { listeners.add (l); } public synchronized void removeChangeListener (ChangeListener l) { listeners.remove (l); } protected synchronized void fireChange () { final ChangeEvent ev = new ChangeEvent (this); final Set l2 = new HashSet (listeners); SwingUtilities.invokeLater (new Runnable () { public void run () { Iterator it = l2.iterator (); while (it.hasNext ()) ((ChangeListener) it.next ()).stateChanged (ev); } }); } public synchronized Task prepare () { if (prepareTask == null) prepareTask = RequestProcessor.postRequest (this); return prepareTask; } public void run () { edit.prepareDocument ().waitFinished (); final Document doc = edit.getDocument (); if (doc == null) { // Should not happen: System.err.println("WARNING: Doc was null!"); return; } doc.render (new Runnable () { public void run () { try { setScoreAndParseException (parse (doc), null); } catch (IOException ioe) { setScoreAndParseException (score, ioe); } catch (BadLocationException ble) { setScoreAndParseException (score, new FoldingIOException (ble)); } } }); doc.addDocumentListener (this); } private synchronized void setScoreAndParseException (Score s, IOException e) { score = s; parseException = e; fireChange (); } public boolean isValid () { return parseException == null; } public void changedUpdate (DocumentEvent ev) { } public void insertUpdate (DocumentEvent ev) { invalidateLater (); } public void removeUpdate (DocumentEvent ev) { invalidateLater (); } private void invalidateLater () { RequestProcessor.postRequest (new Runnable () { public void run () { invalidate (); } }); } protected synchronized void invalidate () { prepareTask = null; fireChange (); } public synchronized void setScore (final Score s) throws IOException { final Score oldScore = score; if (s.equals (oldScore)) { return; } prepareTask = Task.EMPTY; score = s; parseException = null; final StyledDocument doc = edit.openDocument (); final BadLocationException[] e = new BadLocationException[] { null }; try { NbDocument.runAtomic (doc, new Runnable () { public void run () { doc.removeDocumentListener (ScoreSupport.this); try { generate (s, oldScore, doc); } catch (BadLocationException ble) { e[0] = ble; } finally { doc.addDocumentListener (ScoreSupport.this); } } }); if (e[0] != null) throw e[0]; } catch (BadLocationException ble) { throw new FoldingIOException (ble); } fireChange (); } public Score getScore () throws IOException { prepare ().waitFinished (); synchronized (this) { if (parseException != null && ! entry.getDataObject ().isModified ()) { throw parseException; } else if (score != null) { return score; } else if (parseException != null) { throw parseException; } else { // Should not happen: throw new IOException ("parse did not finish as expected"); } } } protected Score parse (Document doc) throws IOException, BadLocationException { String text = doc.getText (0, doc.getLength ()); return Score.parse (new StringReader (text)); } protected void generate (Score s, Score oldScore, Document doc) throws BadLocationException { CharArrayWriter wr = new CharArrayWriter (); try { Score.generate (s, wr); } catch (IOException ioe) { // Should not happen. ioe.printStackTrace (); return; } doc.remove (0, doc.getLength ()); doc.insertString (0, wr.toString (), null); } }